package com.gdteam.kernel.persistence.impl;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.apache.tapestry5.ioc.annotations.EagerLoad;
import org.scannotation.AnnotationDB;
import org.scannotation.ClasspathUrlFinder;
import org.slf4j.Logger;

import com.gdteam.kernel.domain.Domain;
import com.gdteam.kernel.persistence.EntityProvider;
import com.gdteam.kernel.persistence.annotation.KernelPersisted;

@EagerLoad
public class KernelEntityProvider implements EntityProvider {
    
    private Logger log;
    private AnnotationDB db = new AnnotationDB();
    private Collection<Class<? extends Domain>> entities = new ArrayList<Class<? extends Domain>>();
    
    public KernelEntityProvider(Logger log) {
        this.log = log;
        initEntitiesList();
        
    }

    public Collection<Class<? extends Domain>> getEntities() {
        return this.entities;
    }
    
    
    private void initEntitiesList() {
        try {
            db.addIgnoredPackages("javax","org");
            db.setScanFieldAnnotations(false);
            db.setScanMethodAnnotations(false);
            db.setScanParameterAnnotations(false);
            db.setScanClassAnnotations(true);
            
            URL[] urls = ClasspathUrlFinder.findClassPaths();
            db.scanArchives(urls);
            
            Map<String,Set<String>> annotatedClassesMap = db.getAnnotationIndex();
            
            Set<String> classes = annotatedClassesMap.get(KernelPersisted.class.getName());
            
            if (null == classes) {
                log.info("could not find any annotated classes");
                return;
            }
            
            for (String clname : classes) {
                try {
                    Class cl = Class.forName(clname);
                    
                    if (!cl.isInterface()) {
                        try {
                            
                            Domain dmo = (Domain)cl.newInstance();
                            dmo = null;
                            this.entities.add(cl);
                            
                        } catch (Exception e) {
                            log.error("could not understand {} class as a Kernel Domain ", e);
                        }
                    } else {
                        log.warn("found annotated interface {}, not taken into account",cl.getName());
                    }
                    
                } catch (ClassNotFoundException cnfe) {
                    log.error("Could not find class {}",cnfe);
                }
                 
            }
            
        } catch (IOException ioe) {
            log.error(ioe.getMessage());
        }

    }

}
